package com.qiaofang.service.impl;

import com.github.wenhao.jpa.Specifications;
import com.google.common.collect.Lists;
import com.qiaofang.common.constant.DelFlagEnum;
import com.qiaofang.common.constant.ExceptionEnum;
import com.qiaofang.common.exception.BusinessException;
import com.qiaofang.common.model.BaseDomain;
import com.qiaofang.common.model.PageDTO;
import com.qiaofang.common.model.UiListBean;
import com.qiaofang.common.model.UiSelectBean;
import com.qiaofang.common.utils.ChineseCharToEn;
import com.qiaofang.common.utils.DateUtil;
import com.qiaofang.common.utils.PageUtil;
import com.qiaofang.common.utils.StringUtil;
import com.qiaofang.constant.CompanyTypeEnum;
import com.qiaofang.constant.OperationTypeEnum;
import com.qiaofang.constant.RelationStatusEnum;
import com.qiaofang.dto.DepartmentDTO;
import com.qiaofang.dto.DistributionCompanyDTO;
import com.qiaofang.dto.ListDistributionCompanyDTO;
import com.qiaofang.entity.*;
import com.qiaofang.repository.CompanyRelationRepository;
import com.qiaofang.repository.CompanyRepository;
import com.qiaofang.repository.DistributionCompanyRepository;
import com.qiaofang.repository.OtherCompanyRepository;
import com.qiaofang.service.*;
import com.qiaofang.vo.DistributionCompanyVO;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.persistence.criteria.CriteriaBuilder;
import java.util.*;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service
public class DistributionCompanyServiceImpl extends CompanyServiceImpl implements DistributionCompanyService {

    @Autowired
    private CompanyRepository companyRepository;

    @Autowired
    private DistributionCompanyRepository distributionCompanyRepository;

    @Autowired
    private CompanyRelationRepository companyRelationRepository;

    @Autowired
    private DepartmentService departmentService;

    @Autowired
    private OperationLogService operationLogService;

    @Autowired
    private PartnerInfoService partnerInfoService;

    @Autowired
    private PremisesService premisesService;

    @Autowired
    private OtherCompanyRepository otherCompanyRepository;

    @Override
    public UiListBean<DistributionCompanyVO> listDistributionCompany(ListDistributionCompanyDTO dto, PageDTO page) {
        Specification<DistributionCompany> specification = Specifications.<DistributionCompany>and()
                .eq("companyType", CompanyTypeEnum.Intermediary.getType())
                //  .eq(dto.getType() != null, "companyType", dto.getType())
                .eq(StringUtil.isNotBlank(dto.getStatus()), "status", dto.getStatus())
                .eq(dto.getMerchantCompanyId() != null, "merchantCompanyId", dto.getMerchantCompanyId())
                .eq(dto.getProvince() != null, "province", dto.getProvince())
                .eq(dto.getCity() != null, "city", dto.getCity())
                .eq(dto.getZone() != null, "zone", dto.getZone())
                .between(StringUtil.isNotBlank(dto.getCreateTimeStart()), "createTime"
                        , DateUtil.minOfString(dto.getCreateTimeStart()),
                        DateUtil.maxOfString(dto.getCreateTimeEnd()))
                .like(StringUtil.isNotBlank(dto.getSearchContent()), "companyName", StringUtil.addLikeParam(dto.getSearchContent()))
                .eq("delFlag", DelFlagEnum.UNDEL.getNo())
                .build();
        Page<DistributionCompany> companies = distributionCompanyRepository.findAll(specification, PageUtil.getPageByDTO(page, PageUtil.getCreateTimeDesc()));
        UiListBean<DistributionCompanyVO> uiListBean = new UiListBean();
        List<DistributionCompanyVO> vos = Lists.newArrayList();
        if (companies.getContent() != null) {
            List<DistributionCompany> companyList = companies.getContent();
            List<Long> companyIds = companyList.stream().map(BaseDomain::getId).collect(Collectors.toList());
            Map<Long, OtherCompany> otherCompMap = new HashMap<>();
            if(!CollectionUtils.isEmpty(companyIds)){
                List<OtherCompany> otherCompList = otherCompanyRepository.listOtherCompany(companyIds);
                otherCompMap = otherCompList.stream().collect(Collectors.toMap(OtherCompany::getChannelCompanyId, Function.identity(), (oldValue, newValue) -> newValue));
            }

            for (DistributionCompany distributionCompany : companyList) {
                DistributionCompanyVO vo = convertDomain2VO(distributionCompany);
                // 将分销公司绑定的总代关系体现出来
                vo.setIsBindV10(false);
                if(Objects.nonNull(otherCompMap.get(vo.getId()))){
                    vo.setIsBindV10(true);
                }
                vos.add(vo);
            }
        }
        setPartnerInfoName(vos);
        uiListBean.setList(vos);
        uiListBean.setTotalCount(companies.getTotalElements());
        return uiListBean;
    }

    private DistributionCompanyVO convertDomain2VO(DistributionCompany company) {
        DistributionCompanyVO vo = new DistributionCompanyVO();
        vo.setId(company.getId());
        vo.setCompanyUuid(company.getCompanyUuid());
        vo.setCompanyName(company.getCompanyName());
        vo.setStatus(company.getStatus());
        vo.setCompanyType(company.getCompanyType());
        vo.setMerchantCompanyId(company.getMerchantCompanyId());
        vo.setProvince(company.getProvince());
        vo.setCity(company.getCity());
        vo.setZone(company.getZone());
        vo.setAddress(company.getAddress());
        vo.setPartnerInfoId(company.getPartnerInfoId());
        vo.setCreateTime(company.getCreateTime());
        return vo;
    }

    private void setPartnerInfoName(List<DistributionCompanyVO> vos) {
        if (vos != null && vos.size() > 0) {
            List<Long> ids = Lists.newArrayList();
            for (DistributionCompanyVO vo : vos) {
                if (vo.getPartnerInfoId() != null) {
                    ids.add(vo.getPartnerInfoId());
                }
            }
            Map<Long, PartnerInfo> map = partnerInfoService.listPartnerInfo(ids);
            for (DistributionCompanyVO vo : vos) {
                if (vo.getPartnerInfoId() != null) {
                    if (map.containsKey(vo.getPartnerInfoId())) {
                        PartnerInfo partnerInfo = map.get(vo.getPartnerInfoId());
                        vo.setPartnerInfoName(partnerInfo.getAccountName());
                    }
                }
            }
        }
    }

    @Override
    public void addDistributionCompany(DistributionCompanyDTO dto) {
        //判断是否已经存在同名的分销机构
        if (checkCompanyName(dto.getMerchantCompanyId(), dto.getCompanyName())) {
            throw new BusinessException(ExceptionEnum.EXIST_SAME_NAME_DISTRIBUTION);
        }
        //分销
        Company merchant = companyRepository.findById(dto.getMerchantCompanyId())
                .orElseThrow(() -> new BusinessException(ExceptionEnum.NOT_FIND_DB_DATA));
        Company company = new Company();
        company.setCompanyName(dto.getCompanyName());
        company.setCompanyType(CompanyTypeEnum.Intermediary.getType());
        company.setProvince(dto.getProvince());
        company.setCity(dto.getCity());
        company.setZone(dto.getZone());
        company.setAddress(dto.getAddress());
        company.setDelFlag(DelFlagEnum.UNDEL.getNo());
        company.setStatus(dto.getStatus());
        company.setCommissionFlag(merchant.getCommissionFlag());
        company.setMessageFlag(merchant.getMessageFlag());
        company.setCompanyUuid(UUID.randomUUID().toString());
        companyRepository.save(company);
        //更新新增机构的公司代码
        String companyCode = getCompanyCode(company.getCompanyName());
        company.setCompanyCode(companyCode);
        companyRepository.save(company);
        //楼盘关系表中绑定默认全部楼盘
        premisesService.addPremisesRelation(dto.getMerchantCompanyId(), company.getId());
        //关系表
        CompanyRelation companyRelation = new CompanyRelation();
        companyRelation.setDevCompany(dto.getMerchantCompanyId());
        companyRelation.setAgentCompany(company.getId());
        companyRelation.setRelationStatus(RelationStatusEnum.VALID.getNo());
        companyRelation.setDelFlag(DelFlagEnum.UNDEL.getNo());
        companyRelationRepository.save(companyRelation);
        //部门
        departmentService.addTopDepartment(company);
        //操作日志
        operationLogService.addOperationLog(OperationTypeEnum.ADD.getNo(), company.getId());
    }

    /**
     * 原有代码
     *
     * @param companyName 公司名字
     * @return
     */
    private String getCompanyCode(String companyName) {
        String code = "";
        String regEx = "[a-zA-Z]";
        String firstLetter = ChineseCharToEn.getFirstLetter(companyName);
        String pro;
        if (Pattern.matches(regEx, firstLetter)) {
            firstLetter = firstLetter.toUpperCase();
            pro = firstLetter + "%";
        } else {
            pro = "V%";
        }
        if (NumberUtils.isDigits(firstLetter)) {
            firstLetter = "V";
        }
        String dbMaxCode = companyRepository.getMaxCompanyCode(pro);
        if (StringUtil.isNotBlank(dbMaxCode)) {
            String subStr = dbMaxCode.substring(1);
            code = firstLetter + addNum(Integer.parseInt(subStr));
        } else {
            code = firstLetter + "00001";

        }
        return code;
    }

    private String addNum(int i) {
        String str = "";
        int sum = i + 1;
        if ((sum + "").length() == 1) {
            str = "0000" + sum;
        } else if ((sum + "").length() == 2) {
            str = "000" + sum;
        } else if ((sum + "").length() == 3) {
            str = "00" + sum;
        } else if ((sum + "").length() == 4) {
            str = "0" + sum;
        }
        return str;
    }

    private boolean checkCompanyName(Long merchantCompanyId, String companyName) {
        CompanyRelation example = new CompanyRelation();
        example.setDevCompany(merchantCompanyId);
        example.setDelFlag(DelFlagEnum.UNDEL.getNo());
        List<CompanyRelation> companyRelations = companyRelationRepository.findAll(Example.of(example));
        if (companyRelations != null && companyRelations.size() > 0) {
            List<Long> ids = Lists.newArrayList();
            for (CompanyRelation companyRelation : companyRelations) {
                ids.add(companyRelation.getAgentCompany());
            }
            List<Company> companies = companyRepository.findAllById(ids);
            if (companies != null && companies.size() > 0) {
                for (Company company : companies) {
                    if (StringUtil.equals(companyName, company.getCompanyName())) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    @Override
    public void updateDistributionCompany(DistributionCompanyDTO dto) {
        Company company = companyRepository.findById(dto.getId())
                .orElseThrow(() -> new BusinessException(ExceptionEnum.NOT_FIND_DB_DATA));
        //判断是否已经存在同名的分销机构
        if (!StringUtil.equals(company.getCompanyName(), dto.getCompanyName())) {
            if (checkCompanyName(dto.getMerchantCompanyId(), dto.getCompanyName())) {
                throw new BusinessException(ExceptionEnum.EXIST_SAME_NAME_DISTRIBUTION);
            }
        }
        company.setCompanyName(dto.getCompanyName());
        company.setProvince(dto.getProvince());
        company.setCity(dto.getCity());
        company.setZone(dto.getZone());
        company.setAddress(dto.getAddress());
        company.setStatus(dto.getStatus());

        // 更新公司表
        companyRepository.save(company);
        //部门
        departmentService.updateTopDepartment(company, dto.getPartnerInfoId());
        //操作日志
        operationLogService.addOperationLog(OperationTypeEnum.EDIT.getNo(), company.getId());
    }

    @Override
    public DistributionCompanyVO getDistributionCompany(Long id) {
        DistributionCompany company = distributionCompanyRepository.findById(id)
                .orElseThrow(() -> new BusinessException(ExceptionEnum.NOT_FIND_DB_DATA));
        return convertDomain2VO(company);
    }

    @Override
    public List<UiSelectBean> listOptionDistributionCompany(Long merchantCompanyId) {
        Specification<DistributionCompany> specification = Specifications.<DistributionCompany>and()
                .eq("companyType", CompanyTypeEnum.Intermediary.getType())
                .eq(merchantCompanyId != null, "merchantCompanyId", merchantCompanyId)
                .eq("delFlag", DelFlagEnum.UNDEL.getNo())
                .build();
        List<DistributionCompany> companyList =  distributionCompanyRepository.findAll(specification);
        List<UiSelectBean> list = Lists.newArrayList();
        if (companyList != null) {
            for (DistributionCompany company : companyList) {
                UiSelectBean uiSelectBean = new UiSelectBean();
                uiSelectBean.setValue(company.getId());
                uiSelectBean.setLabel(company.getCompanyName());
                list.add(uiSelectBean);
            }
        }
        return list;
    }
}
